﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////


#include "CSVFileManagerDlg.h"
#include "GbmpNew.h"
#include "ui_CSVFileManagerDlg.h"
#include "GmStyleSheetHelper.h"
#include "GnufWorkBench.h"
#include "GnufStyleSheets.h"
#include "GnufStyleSheetComposer.h"
#include "UiCommonDialog.h"
#include "LatestDirManager.h"
#include "FilePath.h"
#include "GbmpFileSystem.h"
#include "CSVFileManager.h"
#include <QDesktopServices>
#include <QUrl>
#include "GnufMessageBoardInterface.h"
#include "JournalUtils.h"
#include "IJournalCommandData.h"
#include "CommandParameters.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gfam;
using namespace gcmp;
namespace
{
    const std::wstring s_dlgTitle = GBMP_TR(L"管理查找表格");
}
CSVFileManagerDlg::CSVFileManagerDlg(gcmp::IDocument* pDoc, QWidget *parent) : gnuf::QtDialog(parent, Qt::FramelessWindowHint)
, m_ui(NEW_AS_OWNER_PTR(Ui::CSVFileManagerDlg))
, m_pDoc(pDoc)
{
    gcmp::OwnerPtr<CSVFileManager> csvFileManager = NEW_AS_OWNER_PTR(CSVFileManager, pDoc);
    m_listModel = NEW_AS_OWNER_PTR(CSVFileListModel, pDoc,TransferOwnership(csvFileManager), parent);
    m_ui->setupUi(this);
    if (gnuf::WorkBench* wb = gnuf::WorkBench::get())
    {
        if (const gnuf::StyleSheetComposer* ssc = wb->styleSheetComposer())
        {
            const_cast<gnuf::StyleSheetComposer*>(ssc)->addStyleSheet(gnuf::StyleSheet::eToQWidget);
            const_cast<gnuf::StyleSheetComposer*>(ssc)->addStyleSheet(gnuf::StyleSheet::eToQLabel);
            const_cast<gnuf::StyleSheetComposer*>(ssc)->addStyleSheet(gnuf::StyleSheet::eToQListView);
            const_cast<gnuf::StyleSheetComposer*>(ssc)->addStyleSheet(gnuf::StyleSheet::eToQGroupBox);
            const_cast<gnuf::StyleSheetComposer*>(ssc)->addStyleSheet(gnuf::StyleSheet::eToQComboBox);
            const_cast<gnuf::StyleSheetComposer*>(ssc)->addStyleSheet(gnuf::StyleSheet::eToQPushButton);
            const_cast<gnuf::StyleSheetComposer*>(ssc)->addStyleSheet(gnuf::StyleSheet::eToQLineEdit);
            setStyleSheet(QString::fromStdString(ssc->toString()));
            std::wstring buttonIconDir[4]{ L"Import", L"Export", L"Delete", L"Help" };
            QPushButton* pbutton[4]{ m_ui->importButton, m_ui->exportButton, m_ui->deleteButton, m_ui->helpButton };
            std::string s0 = "QPushButton{image:url(";
            std::string s2 = ");}";


            std::wstring ws11 = L":image/CSVFileManagerDlg/";
            std::wstring ws12 = L"";
            gnuf::ETheme theme = gnuf::BaseUtil::currentTheme();
            if (gnuf::ETheme::eDark == theme)  ws12 += L"/Dark";
            for (int i = 0; i < 4; i++)
            {
                std::wstring ws1 = ws11 + buttonIconDir[i] + ws12 + L"/16x16.png";
                std::string styleSheet = s0 + StringUtil::ToString(ws1) + s2;
                pbutton[i]->setStyleSheet(styleSheet.c_str());
            }
        }
    }
    else
    {
        GmStyleSheetHelper* pStyleSheetHelper = GmStyleSheetHelper::Instance();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pStyleSheetHelper, L"pStyleSheetHelper指针为空", L"paramodel", L"2024-02-20");
        std::wstring styleSheetStr = pStyleSheetHelper->GetCurrentStyleData();
        setStyleSheet(QString::fromStdWString(styleSheetStr));
    }
    m_ui->gbmp_title->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
    m_ui->gbmp_title->setIconVisible(false);
    m_ui->gbmp_title->setMaxButtonVisible(false);
    m_ui->gbmp_title->setMinButtonVisible(false);
    m_ui->gbmp_title->setCloseButtonVisible(true);
    m_ui->gbmp_title->setTextVisible(true);
    m_ui->gbmp_title->setText(QString::fromStdWString(s_dlgTitle));
    this->setProperty("use_gbmp_title", true);
    setWindowTitle(QString::fromStdWString(s_dlgTitle));
    setMouseTracking(true);
    m_ui->importButton->setToolTip(QString::fromStdWString(L"导入"));
    m_ui->exportButton->setToolTip(QString::fromStdWString(L"导出"));
    m_ui->deleteButton->setToolTip(QString::fromStdWString(L"删除"));
    m_ui->helpButton->setToolTip(QString::fromStdWString(L"查看功能使用方式，下载表格通用模板"));
    connect(m_ui->CloseButton, SIGNAL(clicked()), this, SLOT(CloseButtonPushed()));
    connect(m_ui->gbmp_title, &GmTitleBar::closeRequested, this, &CSVFileManagerDlg::reject);
    connect(m_ui->gbmp_title, &GmTitleBar::moveRequested, this, &CSVFileManagerDlg::onMoveRequested);
    connect(m_ui->importButton, SIGNAL(clicked()), this, SLOT(ImportCSVFile()));
    connect(m_ui->exportButton, SIGNAL(clicked()), this, SLOT(ExportCSVFile()));
    connect(m_ui->deleteButton, SIGNAL(clicked()), this, SLOT(DeleteCSVFile()));
    connect(m_ui->helpButton, SIGNAL(clicked()), this, SLOT(HelpInfo()));

    InitCSVFileList();
    m_ui->gbmp_title->setFocus();
}

void CSVFileManagerDlg::onMoveRequested(const QPoint& cursorPos, const QPoint& offset)
{
    Q_UNUSED(cursorPos);
    move(pos() + offset);
}

CSVFileManagerDlg::~CSVFileManagerDlg()
{
    m_listModel = nullptr;
}

bool gfam::CSVFileManagerDlg::ImportCSVFile()
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_ui, L"m_ui无效", L"paramodel", L"2024-02-20");

    bool isInReplay = JournalUtils::IsInReplay();
    if (isInReplay)
    {
        //此句话需放在最前端，主要为了脚本回放时，能够使下条脚本命令提前执行。
        JournalUtils::RequestWake();
    }
    bool result = false;
    //获取最近打开路径
    std::wstring dirPath = L"";
    LatestDirManager* p_LatestDirManager = LatestDirManager::Get();
    if (p_LatestDirManager)
    {
        dirPath = p_LatestDirManager->GetLatestDir();
    }
    std::wstring filePathName = UiCommonDialog::ShowOpenFileDialog(GBMP_TR(L"导入CSV"), dirPath, L"*.csv");
    GmTitleBar* titleBar = m_ui->gbmp_title;
    if (titleBar==nullptr)
    {
        return false;
    }
    if (filePathName.empty())
    {
        titleBar->setFocus();
        return false;
    }
    FilePath filePath(filePathName);
    //设置最近打开路径
    if (p_LatestDirManager)
    {
        p_LatestDirManager->SetLatestDir(filePath.GetDirectoryName());
    }
    if (!isInReplay)
    {
        gcmp::CommandParameters cmdParams;
        cmdParams[L"FilePath"] = filePathName;
        OwnerPtr<gcmp::IJournalCommandData> opJournalCmdData = IJournalCommandData::Create();
        opJournalCmdData->SetCommandName(L"FilePath");
        opJournalCmdData->SetParameterArray(cmdParams);
        gcmp::JournalUtils::RecordCommand(TransferOwnership(opJournalCmdData));
    }
    try
    {
        std::wstring name = filePath.GetFileNameWithoutExtension();
        std::vector < std::pair < std::wstring, std::wstring >> columnList;
        std::vector<std::vector<std::wstring>> values;
        std::wstring msg;

        DBG_WARN_AND_RETURN_FALSE_UNLESS(m_listModel, L"m_listModel无效", L"paramodel", L"2024-02-20");
        bool isExist = m_listModel->IsCSVFileExist(name);
        if (isExist)
        {
            gnuf::MsgBoardReturnValue ret = gnuf::ShowMessageBoard(StringUtil::FormatWString(L"查找表格 %s 已经存在，要替换它吗？",name.c_str()), GBMP_TR(L"导入查找表格"), true,gnuf::eMB_OKCANCEL | gnuf::eMB_ICONWARNING);
            if (ret==gnuf::MsgBoardReturnValue::eIDOK)
            {
                int index = m_listModel->GetFileIndexByName(name);
                QListView* listView = m_ui->csvListView;
                if (listView==nullptr)
                {
                    return false;
                }
                QAbstractItemModel* model = listView->model();
                if (model==nullptr)
                {
                    return false;
                }
                QModelIndex qIndex = model->index(index, 0);
                listView->setCurrentIndex(qIndex);
                std::wstring retName;
                result = m_listModel->deleteCSVFile(index, retName,msg);
                if (!result)
                {
                    listView->setCurrentIndex(qIndex);
                    gnuf::ShowMessageBoard(L"导入的重名表格已被表达式引用，因此无法替换。如确要替换此表格请先修改所有引用表达式。", GBMP_TR(L"错误"), true, gnuf::eMB_OK | gnuf::eMB_ICONWARNING);
                    titleBar->setFocus();
                    return false;
                }
            }
            else
            {
                titleBar->setFocus();
                return false;
            }
        }
        if (isInReplay)
        {
            CommandParameterValue params = JournalUtils::GetCommandParameter(L"FilePath");
            if (params.IsWString())
            {
                filePathName = params.AsWString();
                if (gcmp::FilePath::IsRelativePath(filePathName))
                {
                    std::wstring logFilePath = JournalUtils::GetReplayFilePath();
                    FilePath logFile(logFilePath);
                    filePathName=gcmp::FilePath::GetAbsolutePath(filePathName, logFile.GetDirectoryName());
                }
            }
        }

        DBG_WARN_AND_RETURN_FALSE_UNLESS(m_listModel, L"m_listModel无效", L"paramodel", L"2024-02-20");
        result = m_listModel->importCSVFile(name, filePathName, msg);
        if (!result)
        {
            gnuf::ShowMessageBoard(msg, GBMP_TR(L"导入查找表格"), true, gnuf::eMB_OK | gnuf::eMB_ICONWARNING);
        }
    }
    catch (FamilyDbException& e)
    {
        gnuf::ShowMessageBoard(e.GetMessageW(), GBMP_TR(L"导入查找表格"), true, gnuf::eMB_OK | gnuf::eMB_ICONWARNING);
    }
    catch (std::exception& e)
    {
        std::wstring error = StringUtil::ToWString(e.what());
        gnuf::ShowMessageBoard(error, GBMP_TR(L"导入查找表格"), true, gnuf::eMB_OK | gnuf::eMB_ICONWARNING);
    }
    QListView* listView = m_ui->csvListView;
    if (listView==nullptr)
    {
        return false;
    }
    QAbstractItemModel* model = listView->model();
    if (model==nullptr)
    {
        return false;
    }
    QModelIndex index = model->index(model->rowCount()-1, 0);
    listView->setCurrentIndex(index);
    titleBar->setFocus();
    return result;
}

bool gfam::CSVFileManagerDlg::ExportCSVFile()
{
    if (!m_ui)
    {
        return false;
    }

    bool result = false;
    //获取最近打开路径
    std::wstring dirPath = L"";
    LatestDirManager* p_LatestDirManager = LatestDirManager::Get();
    if (p_LatestDirManager)
    {
        dirPath = p_LatestDirManager->GetLatestDir();
    }
    std::wstring filePathName = UiCommonDialog::ShowSaveFileDialog(GBMP_TR(L"导出CSV"), dirPath, L"*.csv");
    if (filePathName.empty() && m_ui && m_ui->gbmp_title)
    {
        m_ui->gbmp_title->setFocus();
        return false;
    }
    FilePath filePath(filePathName);
    //设置最近打开路径
    if (p_LatestDirManager)
    {
        p_LatestDirManager->SetLatestDir(filePath.GetDirectoryName());
    }
    try
    {
        std::wstring msg;
        if (!m_ui->csvListView)
        {
            return false;
        }

        QModelIndex index = m_ui->csvListView->currentIndex();

        if (index.row()<0)
        {
            gnuf::ShowMessageBoard(L"请选择要导出的CSV文件", GBMP_TR(L"导出查找表格"), true, gnuf::eMB_OK | gnuf::eMB_ICONWARNING);
            return false;
        }

        DBG_WARN_AND_RETURN_FALSE_UNLESS(m_listModel, L"m_listModel无效", L"paramodel", L"2024-02-20");
        result = m_listModel->exportCSVFile(index.row(), filePathName, msg);
        if (!result)
        {
            gnuf::ShowMessageBoard(msg, GBMP_TR(L"导出查找表格"), true, gnuf::eMB_OK | gnuf::eMB_ICONWARNING);
        }
        else
        {
            gnuf::ShowMessageBoard(L"文件导出成功", GBMP_TR(L"导出查找表格"), true, gnuf::eMB_OK | gnuf::eMB_ICONWARNING);
        }
    }
    catch (FamilyDbException& e)
    {
        gnuf::ShowMessageBoard(e.GetMessageW(), GBMP_TR(L"导出查找表格"), true, gnuf::eMB_OK | gnuf::eMB_ICONWARNING);
    }
    catch (std::exception& e)
    {
        std::wstring error = StringUtil::ToWString(e.what());
        gnuf::ShowMessageBoard(error, GBMP_TR(L"导出查找表格"), true, gnuf::eMB_OK | gnuf::eMB_ICONWARNING);
    }

    if (m_ui && m_ui->gbmp_title)
    {
        m_ui->gbmp_title->setFocus();
    }
    return result;
}

bool gfam::CSVFileManagerDlg::DeleteCSVFile()
{
    bool result = false;
    try
    {
        if (!m_ui)
        {
            return false;
        }

        if (!m_ui->gbmp_title)
        {
            return false;
        }

        if (!m_ui->csvListView)
        {
            return false;
        }

        QModelIndex index = m_ui->csvListView->currentIndex();
        if (index.row()<0)
        {
            gnuf::ShowMessageBoard(L"请选择要删除的CSV文件", GBMP_TR(L"删除查找表格"), true, gnuf::eMB_OK | gnuf::eMB_ICONWARNING);
            if (m_ui && m_ui->gbmp_title)
            {
                m_ui->gbmp_title->setFocus();
            }
            return false;
        }
        DBG_WARN_AND_RETURN_FALSE_UNLESS(m_listModel, L"m_listModel无效", L"paramodel", L"2024-02-20");
        std::wstring fileName =m_listModel->GetFileNameByIndex(index.row());
        gnuf::MsgBoardReturnValue ret = gnuf::ShowMessageBoard(L"是否确实删除此查找表格？", GBMP_TR(L"删除查找表格"), true, gnuf::eMB_OKCANCEL | gnuf::eMB_ICONWARNING);
        if (ret == gnuf::MsgBoardReturnValue::eIDCANCEL)
        {
            if (m_ui && m_ui->gbmp_title)
            {
                m_ui->gbmp_title->setFocus();
            }
            return false;
        } 
        std::wstring msg;
        DBG_WARN_AND_RETURN_FALSE_UNLESS(m_listModel, L"m_listModel无效", L"paramodel", L"2024-02-20");
        result= m_listModel->deleteCSVFile(index.row(),fileName,msg);
        if (!result)
        {
            int index = m_listModel->GetFileIndexByName(fileName);
            QListView* listView = m_ui->csvListView;
            if (listView==nullptr)
            {
                return false;
            }
            QAbstractItemModel* model = listView->model();
            if (model==nullptr)
            {
                return false;
            }
            QModelIndex qIndex = model->index(index, 0);
            listView->setCurrentIndex(qIndex);
            gnuf::ShowMessageBoard(msg, GBMP_TR(L"删除查找表格"), true, gnuf::eMB_OK | gnuf::eMB_ICONWARNING);
        }
    }
    catch (FamilyDbException& e)
    {
        gnuf::ShowMessageBoard(e.GetMessageW(), GBMP_TR(L"删除查找表格"), true, gnuf::eMB_OK | gnuf::eMB_ICONWARNING);
    }
    catch (std::exception& e)
    {
        std::wstring error = StringUtil::ToWString(e.what());
        gnuf::ShowMessageBoard(error, GBMP_TR(L"删除查找表格"), true, gnuf::eMB_OK | gnuf::eMB_ICONWARNING);
    }
    if (m_ui && m_ui->gbmp_title)
    {
        m_ui->gbmp_title->setFocus();
    }
    return result;
}

void gfam::CSVFileManagerDlg::HelpInfo()
{
    if (!m_ui)
    {
        return;
    }

    if (!m_ui->csvListView)
    {
        return;
    }

    QModelIndex index = m_ui->csvListView->currentIndex();
    if (m_ui->gbmp_title)
    {
        m_ui->gbmp_title->setFocus();
    }
    QDesktopServices::openUrl(QStringLiteral("https://www.glodon.com"));
}

void gfam::CSVFileManagerDlg::CloseButtonPushed()
{
    QDialog::accept();
}

void gfam::CSVFileManagerDlg::InitCSVFileList()
{
    try
    {
        //加载默认CSV文件
        std::wstring msg;
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_listModel, L"m_listModel无效", L"paramodel", L"2024-02-20");
        int nums =m_listModel->rowCount(QModelIndex());
        if (nums<=0)
        {
            QString defaultFileDir = QString("%1/component_editor_config/AppParamodel/CommonCSVFile").arg(QCoreApplication::applicationDirPath());
            bool isDefaultLoad = m_listModel->LoadDefaultCSVFile(defaultFileDir.toStdWString(), msg);
            if (!isDefaultLoad)
            {
                gnuf::ShowMessageBoard(L"加载默认CSV文件失败", GBMP_TR(L"初始化查找表格"), true, gnuf::eMB_OK | gnuf::eMB_ICONWARNING);
            }
        }
        // 绑定model
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_ui, L"m_ui无效", L"paramodel", L"2024-02-20");
        QListView* listView = m_ui->csvListView;
        DBG_WARN_AND_RETURN_VOID_UNLESS(listView, L"listView无效", L"paramodel", L"2024-02-20");
        listView->setModel(m_listModel.get());
        listView->setViewMode(QListView::ListMode);
        listView->setDragEnabled(false);
        DBG_WARN_AND_RETURN_VOID_UNLESS(listView->model(), L"listView->model()无效", L"paramodel", L"2024-02-20");
        QModelIndex index =listView->model()->index(0, 0);
        listView->setCurrentIndex(index);
    }
    catch (FamilyDbException& e)
    {
        gnuf::ShowMessageBoard(e.GetMessageW(), GBMP_TR(L"初始化查找表格"), true, gnuf::eMB_OK | gnuf::eMB_ICONWARNING);
    }
    catch (std::exception& e)
    {
        std::wstring error = StringUtil::ToWString(e.what());
        gnuf::ShowMessageBoard(error, GBMP_TR(L"初始化查找表格"), true, gnuf::eMB_OK | gnuf::eMB_ICONWARNING);
    }
}

